#include "XCollada.h"
#include "tinyxml2\tinyxml2.h"
#include <sstream>
using namespace XColladaNamespace;
using namespace tinyxml2;
std::vector<std::string> SplitString(const std::string &s)
{
	std::stringstream ss(s);
	std::istream_iterator<std::string> begin(ss);
	std::istream_iterator<std::string> end;
	std::vector<std::string> vstrings(begin, end);
	return vstrings;
}
void WriteBinaryString(FILE *file, const std::string &s)
{
	unsigned int size = s.size();
	fwrite(&size, sizeof(unsigned int), 1, file);
	fwrite(s.c_str(), sizeof(char), size, file);
}
void XCollada::InitFromOpenCollada(char *buffer)
{
	tinyxml2::XMLDocument doc;
	doc.Parse( buffer );
	if(doc.ErrorID() != 0)
	{
		return;
	}
	XMLElement* root = doc.FirstChildElement("COLLADA");
	version = root->Attribute("version");
	XMLElement* library_effects = root->FirstChildElement("library_effects");
	XMLElement* effect = library_effects->FirstChildElement("effect");
	while(effect)
	{
		Effect* effectXCollada = new Effect;
		effectXCollada->id = effect->Attribute("id");
		XMLElement* profile_CG = effect->FirstChildElement("profile_CG");
		XMLElement* include = profile_CG->FirstChildElement("include");
		effectXCollada->effectName = include->Attribute("sid");
		XMLElement* newparam = profile_CG->FirstChildElement("newparam");
		while(newparam)
		{
			Uniform* uniformXCollada = new Uniform();
			uniformXCollada->name = newparam->Attribute("sid");
			XMLElement* newparamChild = newparam->FirstChildElement();
			std::string typeName = newparamChild->Name();
			if(typeName.compare("float") == 0)
			{
				uniformXCollada->type = SUT_float;
				std::vector<std::string> buffer = SplitString(newparamChild->GetText());
				for(int i = 0; i < buffer.size(); i++)
				{
					uniformXCollada->floatData[i] = atof((buffer[i]).c_str());
				}
			}
			else if(typeName.compare("float2") == 0)
			{
				uniformXCollada->type = SUT_float2;
				std::vector<std::string> buffer = SplitString(newparamChild->GetText());
				for(int i = 0; i < buffer.size(); i++)
				{
					uniformXCollada->floatData[i] = atof((buffer[i]).c_str());
				}
			}
			else if(typeName.compare("float3") == 0)
			{
				uniformXCollada->type = SUT_float3;
				std::vector<std::string> buffer = SplitString(newparamChild->GetText());
				for(int i = 0; i < buffer.size(); i++)
				{
					uniformXCollada->floatData[i] = atof((buffer[i]).c_str());
				}
			}
			else if(typeName.compare("float4") == 0)
			{
				uniformXCollada->type = SUT_float4;
				std::vector<std::string> buffer = SplitString(newparamChild->GetText());
				for(int i = 0; i < buffer.size(); i++)
				{
					uniformXCollada->floatData[i] = atof((buffer[i]).c_str());
				}
			}
			else if(typeName.compare("surface") == 0)
			{
				uniformXCollada->type = SUT_Texture2D;
				uniformXCollada->textureName = newparamChild->FirstChildElement("init_from")->GetText();
			}
			else if(typeName.compare("sampler2D") == 0)
			{
				uniformXCollada->type = SUT_SamplerState;
			}
			else if(typeName.compare("int") == 0)
			{
				uniformXCollada->type = SUT_int;
				uniformXCollada->intData = atoi(newparamChild->GetText());
			}
			if(strstr(uniformXCollada->name.c_str(), "ignorethis_") == NULL)
			{
				effectXCollada->uniforms.push_back(uniformXCollada);
			}
			else
			{
				effectXCollada->uniformsIgnored.push_back(uniformXCollada);
			}
			newparam = newparam->NextSiblingElement("newparam");
		}
		this->effects.push_back(effectXCollada);
		effect = effect->NextSiblingElement("effect");
	}

	XMLElement* library_materialsXML = root->FirstChildElement("library_materials");
	XMLElement* material = library_materialsXML->FirstChildElement("material");
	while(material)
	{
		Material* materialXCollada = new Material;
		materialXCollada->id = material->Attribute("id");
		materialXCollada->name = material->Attribute("name");
		XMLElement* instance_effect = material->FirstChildElement("instance_effect");
		if(instance_effect)
		{
			char effectID[128];
			strcpy(effectID, instance_effect->Attribute("url") + 1);
			for(std::vector<Effect*>::iterator it = effects.begin(); it != effects.end(); it++)
			{
				if(strcmp((*it)->id.c_str(), effectID) == 0)
				{
					materialXCollada->effect = (*it);
					break;
				}
			}
		}
		library_materials.push_back(materialXCollada);
		material = material->NextSiblingElement("material");
	}

	XMLElement* library_geometriesXML = root->FirstChildElement("library_geometries");
	XMLElement* geometryXML = library_geometriesXML->FirstChildElement("geometry");
	while (geometryXML)
	{
		Geometry* geometry = new Geometry();
		geometry->id = geometryXML->Attribute("id");
		geometry->name = geometryXML->Attribute("name");
		
		XMLElement* mesh = geometryXML->FirstChildElement("mesh");
		XMLElement* source = mesh->FirstChildElement("source");
		while(source)
		{
			MeshSource* meshSource = new MeshSource();
			meshSource->id = source->Attribute("id");
			XMLElement* float_array = source->FirstChildElement("float_array");
			std::vector<std::string> floatList = SplitString(float_array->GetText());
			meshSource->data = new float[floatList.size()];
			meshSource->floatCount = floatList.size();
			for(int i = 0;i<floatList.size();i++)
			{
				meshSource->data[i] = atof(floatList[i].c_str());
			}
			
			XMLElement* technique_common = source->FirstChildElement("technique_common");
			if(technique_common)
			{
				XMLElement* accessor = technique_common->FirstChildElement("accessor");
				if(accessor)
				{
					meshSource->stride = atoi(accessor->Attribute("stride"));
				}
			}
			
			geometry->mesh->meshSources.push_back(meshSource);
			source = source->NextSiblingElement("source");
		}
		XMLElement* verticesXML = mesh->FirstChildElement("vertices");
		while(verticesXML)
		{
			Vertices* vertices = new Vertices();
			vertices->id = verticesXML->Attribute("id");
			XMLElement* input = verticesXML->FirstChildElement("input");
			while(input)
			{
				std::string semantic = input->Attribute("semantic");
				MeshVerticesInput* meshverticesInput = new MeshVerticesInput();
				meshverticesInput->source = input->Attribute("source");
				if(semantic.compare("POSITION") == 0)
				{
					meshverticesInput->semantic = SMT_Position;
				}
				else if(semantic.compare("TEXCOORD") == 0)
				{
					meshverticesInput->semantic = SMT_Texcoord;
				}
				else if(semantic.compare("NORMAL") == 0)
				{
					meshverticesInput->semantic = SMT_Normal;
				}
				else
				{
					meshverticesInput->semantic = SMT_unknown;
				}
				vertices->inputs.push_back(meshverticesInput);
				input = input->NextSiblingElement("input");
			}
			geometry->mesh->verticesList.push_back(vertices);
			verticesXML = verticesXML->NextSiblingElement("vertices");
		}
		XMLElement* triangles = mesh->FirstChildElement("triangles");
		if(triangles)
		{
			geometry->mesh->triangles->triangleCount = atoi(triangles->Attribute("count"));
			//MeshTriangles trianglesXCollada;
			XMLElement* p = triangles->FirstChildElement("p");
			if(p)
			{
				std::vector<std::string> indexList = SplitString(p->GetText());
				geometry->mesh->triangles->indexCount = indexList.size();
				geometry->mesh->triangles->stride = geometry->mesh->triangles->indexCount/(geometry->mesh->triangles->triangleCount*3);
				geometry->mesh->triangles->indexArray = new unsigned int[geometry->mesh->triangles->indexCount];
				for(int i = 0;i<geometry->mesh->triangles->indexCount;i++)
				{
					geometry->mesh->triangles->indexArray[i] = atoi(indexList[i].c_str());
				}
				//Modify culling mode
				unsigned int* temp = new unsigned int[geometry->mesh->triangles->stride];
				int byteNum = geometry->mesh->triangles->stride * sizeof(unsigned int);
				for(int i = 0; i < geometry->mesh->triangles->triangleCount; i++)
				{
					//Each triangle
					memcpy(temp, geometry->mesh->triangles->indexArray + (i*3 + 1) * geometry->mesh->triangles->stride, byteNum);
					memcpy(geometry->mesh->triangles->indexArray + (i*3 + 1) * geometry->mesh->triangles->stride, geometry->mesh->triangles->indexArray + (i*3 + 2) * geometry->mesh->triangles->stride, byteNum);
					memcpy(geometry->mesh->triangles->indexArray + (i*3 + 2) * geometry->mesh->triangles->stride, temp, byteNum);
				}
				delete[] temp;
			}
			XMLElement* input = triangles->FirstChildElement("input");
			while(input)
			{
				MeshTrianglesInput* inputXCollada = new MeshTrianglesInput();
				inputXCollada->offset = atoi(input->Attribute("offset"));
				std::string semantic = input->Attribute("semantic");
				if(semantic.compare("VERTEX") == 0)
				{
					inputXCollada->semantic = SMT_Vertex;
					std::string inputSource = input->Attribute("source");
					inputSource.erase(0, 1);
					for(int i = 0;i < geometry->mesh->verticesList.size(); i++)
					{
						if(inputSource.compare(geometry->mesh->verticesList[i]->id) == 0)
						{
							for(int j = 0; j < geometry->mesh->verticesList[i]->inputs.size(); j++)
							{
								std::string verticesSource = geometry->mesh->verticesList[i]->inputs[j]->source;
								verticesSource.erase(0, 1);
								for(int k = 0; k < geometry->mesh->meshSources.size(); k++)
								{
									if(verticesSource.compare(geometry->mesh->meshSources[k]->id) == 0)
									{
										inputXCollada->meshSource = geometry->mesh->meshSources[k];
										break;
									}
								}
							}
							break;
						}
					}
				}
				else if(semantic.compare("TEXCOORD") == 0)
				{
					inputXCollada->semantic = SMT_Texcoord;
					std::string inputSource = input->Attribute("source");
					inputSource.erase(0, 1);
					for(int i = 0;i < geometry->mesh->meshSources.size(); i++)
					{
						if(inputSource.compare(geometry->mesh->meshSources[i]->id) == 0)
						{
							inputXCollada->meshSource = geometry->mesh->meshSources[i];
							break;
						}
					}
				}
				else if(semantic.compare("NORMAL") == 0)
				{
					inputXCollada->semantic = SMT_Normal;
					std::string inputSource = input->Attribute("source");
					inputSource.erase(0, 1);
					for(int i = 0;i < geometry->mesh->meshSources.size(); i++)
					{
						if(inputSource.compare(geometry->mesh->meshSources[i]->id) == 0)
						{
							inputXCollada->meshSource = geometry->mesh->meshSources[i];
							break;
						}
					}
				}
				else
				{
					inputXCollada->semantic = SMT_unknown;
				}

				geometry->mesh->triangles->inputs.push_back(inputXCollada);
				input = input->NextSiblingElement("input");
			}
			/*
			for(int i = 0; i < geometry->mesh->triangles->inputs.size(); i++)
			{
				unsigned int offsetInIndex = 0;
				for(int j = 0; j < geometry->mesh->triangles->inputs.size(); j++)
				{
					if(geometry->mesh->triangles->inputs[j]->offset < geometry->mesh->triangles->inputs[i]->offset)
					{
						offsetInIndex += geometry->mesh->triangles->inputs[j]->meshSource->stride;
						break;
					}
				}
				geometry->mesh->triangles->inputs[i]->offsetInIndex = offsetInIndex;
			}
			*/
		}
		library_geometries.push_back(geometry);
		geometryXML = geometryXML->NextSiblingElement("geometry");
	}
	XMLElement* library_visual_scenes = root->FirstChildElement("library_visual_scenes");
	XMLElement* visual_scene = library_visual_scenes->FirstChildElement("visual_scene");
	while(visual_scene)
	{
		VisualScene* visualScene = new VisualScene();
		XMLElement* node = visual_scene->FirstChildElement("node");
		while(node)
		{
			Node* XColladaNode = new Node();;
			std::string id = "";
			if(node->Attribute("id")) id = node->Attribute("id");
			XColladaNode->id = id;
			XColladaNode->name = node->Attribute("name");
				
			XMLElement* nodeTransform = node->FirstChildElement(); //Collada use post-multiplication of column-major matrices or pre-multiplication of row-major matrices
			while(nodeTransform)
			{
				if(strcmp(nodeTransform->Name(),"translate") == 0)
				{
					std::vector<std::string> xyz = SplitString(nodeTransform->GetText());
					float x = atof(xyz[0].c_str());
					float y = atof(xyz[1].c_str());
					float z = atof(xyz[2].c_str());
					Matrix matrix;
					matrix.SetTranslate(x,y,z);
					matrix.ConvertRHToLH();
					XColladaNode->transform =  matrix*XColladaNode->transform;
				}
				else if(strcmp(nodeTransform->Name(),"rotate") == 0)
				{
					std::vector<std::string> xyza = SplitString(nodeTransform->GetText());
					float x = atof(xyza[0].c_str());
					float y = atof(xyza[1].c_str());
					float z = atof(xyza[2].c_str());
					float a = (atof(xyza[3].c_str())/180.f)*3.1416f;
					Matrix matrix;
					matrix.SetRotateAxis(a, x, y, z);
					matrix.ConvertRHToLH();
					XColladaNode->transform = matrix*XColladaNode->transform;
				}
				else if(strcmp(nodeTransform->Name(),"scale") == 0)
				{
					std::vector<std::string> xyz = SplitString(nodeTransform->GetText());
					float x = atof(xyz[0].c_str());
					float y = atof(xyz[1].c_str());
					float z = atof(xyz[2].c_str());
					Matrix matrix;
					matrix.SetScale(x,y,z);
					matrix.ConvertRHToLH();
					XColladaNode->transform = matrix*XColladaNode->transform;
				}
				nodeTransform = nodeTransform->NextSiblingElement();
			}
			//Convert to left hand http://msdn.microsoft.com/en-us/library/cc526973.aspx
			//http://www.gamedev.net/topic/385001-converting-a-transformation-matrix-from-right-handed-to-left-handed-coord-system/
			XColladaNode->transform.ConvertZ_upToY_up();
			XMLElement* instance_geometryXML = node->FirstChildElement("instance_geometry");
			while(instance_geometryXML)
			{
				InstanceGeometry* instanceGeometry = new InstanceGeometry();
				std::string url = instance_geometryXML->Attribute("url");
				url.erase(0, 1);
				for(std::vector<Geometry*>::iterator it = library_geometries.begin(); it != library_geometries.end(); it++)
				{
					if((*it)->id.compare(url) == 0)
					{
						instanceGeometry->geometry = (*it);
						break;
					}
				}
				XMLElement* bind_materialXML = instance_geometryXML->FirstChildElement("bind_material");
				if(bind_materialXML)
				{
					XMLElement* technique_commonXML = bind_materialXML->FirstChildElement("technique_common");
					XMLElement* instance_materialXML = technique_commonXML->FirstChildElement("instance_material");
					while(instance_materialXML)
					{
						std::string target = instance_materialXML->Attribute("target");
						target.erase(0, 1);
						for(std::vector<Material*>::iterator it = library_materials.begin(); it != library_materials.end(); it++)
						{
							if(target.compare((*it)->id) == 0)
							{
								instanceGeometry->material = (*it);
								break;
							}
						}
						instance_materialXML = instance_materialXML->NextSiblingElement("instance_material");
					}
				}
				XColladaNode->geometryList.push_back(instanceGeometry);
				instance_geometryXML = instance_geometryXML->NextSiblingElement("instance_geometry");
			}
			if(node->Attribute("id")) visualScene->nodes.push_back(XColladaNode);
			node = node->NextSiblingElement("node");
		}
		this->visualScenes.push_back(visualScene);
		visual_scene = visual_scene->NextSiblingElement("visual_scene");
	}
}
void XCollada::WriteToXColladaFile(char *filePath)
{
	FILE * file;
	file = fopen (filePath, "wb");
	unsigned int sizeInt;
	unsigned char sizeChar;
	WriteBinaryString(file, version); //version
	WriteBinaryString(file, "nodes");
	sizeInt = visualScenes[0]->nodes.size();
	fwrite(&sizeInt, sizeof(unsigned int), 1, file); //number of nodes
	for(std::vector<Node*>::iterator it = visualScenes[0]->nodes.begin(); it != visualScenes[0]->nodes.end(); it++)
	{
		WriteBinaryString(file, (*it)->id);
		WriteBinaryString(file, (*it)->name);
		WriteBinaryString(file, "transform");
		fwrite((*it)->transform, sizeof(float), 16, file); //transform
		WriteBinaryString(file, "geometries");
		sizeInt = (*it)->geometryList.size();
		fwrite(&sizeInt, sizeof(unsigned int), 1, file); //number of geometry
		for(std::vector<InstanceGeometry*>::iterator it2 = (*it)->geometryList.begin(); it2 != (*it)->geometryList.end(); it2++)
		{
			WriteBinaryString(file, (*it2)->geometry->id);
			WriteBinaryString(file, (*it2)->geometry->name);
			WriteBinaryString(file, "material");
			WriteBinaryString(file, (*it2)->material->effect->effectName);
			WriteBinaryString(file, "uniforms");
			sizeChar = (*it2)->material->effect->uniforms.size();
			fwrite(&sizeChar, sizeof(unsigned char), 1, file);
			for(std::vector<Uniform*>::iterator it3 = (*it2)->material->effect->uniforms.begin(); it3 != (*it2)->material->effect->uniforms.end(); it3++)
			{
				WriteBinaryString(file, (*it3)->name);
				sizeChar = (*it3)->type;
				fwrite(&sizeChar, sizeof(unsigned char), 1, file);
				switch((*it3)->type)
				{
				case SUT_float:
				case SUT_float2:
				case SUT_float3:
				case SUT_float4:
					fwrite((*it3)->floatData, sizeof(float), (*it3)->type - SUT_float + 1, file);
					break;
				case SUT_matrix2x2:
					fwrite((*it3)->floatData, sizeof(float), 4, file);
					break;
				case SUT_matrix3x3:
					fwrite((*it3)->floatData, sizeof(float), 9, file);
					break;
				case SUT_matrix4x4:
					fwrite((*it3)->floatData, sizeof(float), 16, file);
					break;
				case SUT_Texture2D:
					WriteBinaryString(file, (*it3)->textureName);
					break;
				case SUT_SamplerState:
					/* //Ignore all sampler state
					sizeChar = (*it3)->wrapModeU;
					fwrite(&sizeChar, sizeof(unsigned char), 1, file);
					sizeChar = (*it3)->wrapModeV;
					fwrite(&sizeChar, sizeof(unsigned char), 1, file);
					sizeChar = (*it3)->wrapModeW;
					fwrite(&sizeChar, sizeof(unsigned char), 1, file);
					sizeChar = (*it3)->filterMin;
					fwrite(&sizeChar, sizeof(unsigned char), 1, file);
					sizeChar = (*it3)->filterMag;
					fwrite(&sizeChar, sizeof(unsigned char), 1, file);
					*/
					//---------- WrapMode
					WrapMode wrapMode = WM_unknown;
					std::string cadidateName = "ignorethis_";
					cadidateName.append((*it3)->name);
					cadidateName.append("_WrapMode");
					for(std::vector<Uniform*>::iterator it4 = (*it2)->material->effect->uniformsIgnored.begin(); it4 != (*it2)->material->effect->uniformsIgnored.end(); it4++)
					{
						if((*it4)->name.compare(cadidateName) == 0)
						{
							switch((*it4)->intData)
							{
							case 0:
								wrapMode = WM_Repeat;
								break;
							case 1:
								wrapMode = WM_Clamp;
								break;
							}
							break;
						}
					}
					fwrite(&wrapMode, sizeof(WrapMode), 1, file);
					//
					break;
				}
			}
			//index
			//WriteBinaryString(file, "index");
			//fwrite(&((*it2)->geometry->mesh->triangles->indexCount), sizeof(unsigned int), 1, file);
			//fwrite((*it2)->geometry->mesh->triangles->indexArray, sizeof(unsigned int), (*it2)->geometry->mesh->triangles->indexCount, file);
			//position
			WriteBinaryString(file, "position");
			bool found = false;
			for(std::vector<MeshTrianglesInput*>::iterator it3 = (*it2)->geometry->mesh->triangles->inputs.begin(); it3 != (*it2)->geometry->mesh->triangles->inputs.end(); it3++)
			{
				if((*it3)->semantic == SMT_Vertex)
				{
					unsigned int count = (*it2)->geometry->mesh->triangles->triangleCount * 3 * (*it3)->meshSource->stride;
					fwrite(&count, sizeof(unsigned int), 1, file);
					float* buffer = new float[count];
					for(int i = 0 ; i < (*it2)->geometry->mesh->triangles->triangleCount * 3 ; i++)
					{
						unsigned int index = (*it2)->geometry->mesh->triangles->indexArray[i*(*it2)->geometry->mesh->triangles->stride + (*it3)->offset];
						for(int j = 0; j < (*it3)->meshSource->stride ; j++)
						{
							if( j < (*it3)->meshSource->stride - 1)
							{
								buffer[i*(*it3)->meshSource->stride + j] = (*it3)->meshSource->data[index*(*it3)->meshSource->stride + j];
							}
							else
							{
								buffer[i*(*it3)->meshSource->stride + j] = -((*it3)->meshSource->data[index*(*it3)->meshSource->stride + j]);
							}
						}
					}
					fwrite(buffer, sizeof(float), count, file);
					found = true;
					break;
				}
			}
			if(found == false)
			{
				unsigned int tempSize = 0;
				fwrite(&(tempSize), sizeof(unsigned int), 1, file);
			}
			//texcoord
			WriteBinaryString(file, "texcoord");
			found = false;
			for(std::vector<MeshTrianglesInput*>::iterator it3 = (*it2)->geometry->mesh->triangles->inputs.begin(); it3 != (*it2)->geometry->mesh->triangles->inputs.end(); it3++)
			{
				if((*it3)->semantic == SMT_Texcoord)
				{
					int texcoordStride = 2;
					unsigned int count = (*it2)->geometry->mesh->triangles->triangleCount * 3 * texcoordStride;
					fwrite(&count, sizeof(unsigned int), 1, file);
					float* buffer = new float[count];
					for(int i = 0 ; i < (*it2)->geometry->mesh->triangles->triangleCount * 3 ; i++)
					{
						unsigned int index = (*it2)->geometry->mesh->triangles->indexArray[i*(*it2)->geometry->mesh->triangles->stride + (*it3)->offset];
						//for(int j = 0; j < texcoordStride ; j++)
						{
							//buffer[i*texcoordStride + j] = (*it3)->meshSource->data[index*(*it3)->meshSource->stride + j];
							buffer[i*texcoordStride] = (*it3)->meshSource->data[index*(*it3)->meshSource->stride];
							buffer[i*texcoordStride + 1] = 1.0f - (*it3)->meshSource->data[index*(*it3)->meshSource->stride + 1];
						}
					}
					fwrite(buffer, sizeof(float), count, file);
					found = true;
					break;
				}
			}
			if(found == false)
			{
				unsigned int tempSize = 0;
				fwrite(&(tempSize), sizeof(unsigned int), 1, file);
			}
			//normal
			WriteBinaryString(file, "normal");
			found = false;
			for(std::vector<MeshTrianglesInput*>::iterator it3 = (*it2)->geometry->mesh->triangles->inputs.begin(); it3 != (*it2)->geometry->mesh->triangles->inputs.end(); it3++)
			{
				if((*it3)->semantic == SMT_Normal)
				{
					unsigned int count = (*it2)->geometry->mesh->triangles->triangleCount * 3 * (*it3)->meshSource->stride;
					fwrite(&count, sizeof(unsigned int), 1, file);
					float* buffer = new float[count];
					for(int i = 0 ; i < (*it2)->geometry->mesh->triangles->triangleCount * 3 ; i++)
					{
						unsigned int index = (*it2)->geometry->mesh->triangles->indexArray[i*(*it2)->geometry->mesh->triangles->stride + (*it3)->offset];
						for(int j = 0; j < (*it3)->meshSource->stride ; j++)
						{
							
							buffer[i*(*it3)->meshSource->stride + j] = (*it3)->meshSource->data[index*(*it3)->meshSource->stride + j];
						}
					}
					fwrite(buffer, sizeof(float), count, file);
					found = true;
					break;
				}
			}
			if(found == false)
			{
				unsigned int tempSize = 0;
				fwrite(&(tempSize), sizeof(unsigned int), 1, file);
			}
			//tangent
			WriteBinaryString(file, "tangent");
			found = false;
			for(std::vector<MeshTrianglesInput*>::iterator it3 = (*it2)->geometry->mesh->triangles->inputs.begin(); it3 != (*it2)->geometry->mesh->triangles->inputs.end(); it3++)
			{
				if((*it3)->semantic == SMT_Tangent)
				{
					unsigned int count = (*it2)->geometry->mesh->triangles->triangleCount * 3 * (*it3)->meshSource->stride;
					fwrite(&count, sizeof(unsigned int), 1, file);
					float* buffer = new float[count];
					for(int i = 0 ; i < (*it2)->geometry->mesh->triangles->triangleCount * 3 ; i++)
					{
						unsigned int index = (*it2)->geometry->mesh->triangles->indexArray[i*(*it2)->geometry->mesh->triangles->stride + (*it3)->offset];
						for(int j = 0; j < (*it3)->meshSource->stride ; j++)
						{
							
							buffer[i*(*it3)->meshSource->stride + j] = (*it3)->meshSource->data[index*(*it3)->meshSource->stride + j];
						}
					}
					fwrite(buffer, sizeof(float), count, file);
					found = true;
					break;
				}
			}
			if(found == false)
			{
				unsigned int tempSize = 0;
				fwrite(&(tempSize), sizeof(unsigned int), 1, file);
			}
			//binormal
			WriteBinaryString(file, "binormal");
			found = false;
			for(std::vector<MeshTrianglesInput*>::iterator it3 = (*it2)->geometry->mesh->triangles->inputs.begin(); it3 != (*it2)->geometry->mesh->triangles->inputs.end(); it3++)
			{
				if((*it3)->semantic == SMT_Binormal)
				{
					unsigned int count = (*it2)->geometry->mesh->triangles->triangleCount * 3 * (*it3)->meshSource->stride;
					fwrite(&count, sizeof(unsigned int), 1, file);
					float* buffer = new float[count];
					for(int i = 0 ; i < (*it2)->geometry->mesh->triangles->triangleCount * 3 ; i++)
					{
						unsigned int index = (*it2)->geometry->mesh->triangles->indexArray[i*(*it2)->geometry->mesh->triangles->stride + (*it3)->offset];
						for(int j = 0; j < (*it3)->meshSource->stride ; j++)
						{
							
							buffer[i*(*it3)->meshSource->stride + j] = (*it3)->meshSource->data[index*(*it3)->meshSource->stride + j];
						}
					}
					fwrite(buffer, sizeof(float), count, file);
					found = true;
					break;
				}
			}
			if(found == false)
			{
				unsigned int tempSize = 0;
				fwrite(&(tempSize), sizeof(unsigned int), 1, file);
			}
		}
	}
	/*
	sizeInt = effects.size();
	fwrite(&sizeInt, sizeof(unsigned int), 1, file); //number of Effect
	for(std::vector<Effect>::iterator it = effects.begin(); it != effects.end(); it++)
	{
		WriteBinaryString(file, (*it).shaderName); //shader name
		sizeChar = (*it).uniforms.size();
		fwrite(&sizeChar, sizeof(unsigned char), 1, file); //number of Uniform
		for(std::vector<Uniform>::iterator it2 = (*it).uniforms.begin(); it2 != (*it).uniforms.end(); it2++)
		{
			WriteBinaryString(file, (*it2).name); //uniform name
			sizeChar = (*it2).type;
			fwrite(&sizeChar, sizeof(unsigned char), 1, file); //uniform type
			switch((*it2).type)
			{
			case SUT_float:
				fwrite((*it2).floatData, sizeof(float), 1, file);
				break;
			case SUT_float2:
				fwrite((*it2).floatData, sizeof(float), 2, file);
				break;
			case SUT_float3:
				fwrite((*it2).floatData, sizeof(float), 3, file);
				break;
			case SUT_float4:
				fwrite((*it2).floatData, sizeof(float), 4, file);
				break;
			case SUT_matrix2x2:
				fwrite((*it2).floatData, sizeof(float), 4, file);
				break;
			case SUT_matrix3x3:
				fwrite((*it2).floatData, sizeof(float), 9, file);
				break;
			case SUT_matrix4x4:
				fwrite((*it2).floatData, sizeof(float), 16, file);
				break;
			case SUT_Texture2D:
				WriteBinaryString(file, (*it2).textureName); //texture name
				break;
			}
		}
	}
	*/
	fclose (file);
}
